﻿using System;
using System.Text;
using System.Diagnostics;
using Newtonsoft.Json;
using Core.Sdk.WeiXin.Domain;
using BrnMall.WeiXin.Sdk;
using System.Security.Cryptography;
using Core.Configuration.Helper;
using Core.Sdk.WeiXin.Tool;
using Core.Sdk.WeiXin.Domain.pay;
using Core.Sdk.Util;
using Core.Configuration.Utils;

namespace Core.Sdk.WeiXin
{
    public class WeiXinSdk
    {
        #region 用户相关
        public static async Task<SessionResult> GetSessionResult(string code, string appId, string secret)
        {
            var url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";
            try
            {
                var json = await HttpHelper.GetAsync(url);
                
                Log($"手机号登录:{url}\r\n{json}");
                var result = JsonConvert.DeserializeObject<SessionResult>(json);
                return result;
            }
            catch (Exception e)
            {
                Trace.TraceError(e.StackTrace);
                throw;
            }
        }

        /// <summary>
        /// 解密用户信息
        /// </summary>
        public static WXUserInfo DecryptUserInfo(string sessionKey, string encryptedData, string iv)
        {
            var tkey = Convert.FromBase64String(sessionKey);
            var tdata = Convert.FromBase64String(encryptedData);
            var tiv = Convert.FromBase64String(iv);
            var jsonString = string.Empty;
            //方式一
            using (var aes = new AesCryptoServiceProvider())
            {
                aes.IV = tiv;
                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;
                aes.Key = tkey;
                using (var ms = new MemoryStream())
                {
                    using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(tdata, 0, tdata.Length);
                        cs.FlushFinalBlock();
                    }
                    var r = ms.ToArray();
                    jsonString = RemoveEmoji(Encoding.UTF8.GetString(r));
                }
            }
            Log($"用户解密后:{jsonString}");
            return JsonConvert.DeserializeObject<WXUserInfo>(jsonString);
        }

        #endregion
        #region 支付相关

        /// <summary>
        /// 小程序支付
        /// </summary>
        /// <param name="req"></param>
        /// <param name="mchKey"></param>
        /// <returns></returns>
        public static PayDto Pay(RequestHandler req, string mchKey)
        {
            string postData = req.parseXML();

            var result = HttpHelper.PostAsync("https://api.mch.weixin.qq.com/pay/unifiedorder", postData).GetAwaiter().GetResult();
            var res = new ResponseHandler(result);

            Log($"Pay 支付:{postData}\r\n response:{result}");
            ShowErrorMsg(res);
            return GetPaySign(req, res.getParameter("prepay_id"), mchKey);
        }

        /// <summary>
        /// 生成客户端支付参数
        /// </summary>
        /// <param name="req"></param>
        /// <param name="prepay_id"></param>
        /// <param name="mchKey"></param>
        /// <returns></returns>
        private static PayDto GetPaySign(RequestHandler req, string prepay_id, string mchKey)
        {
            string timeStamp = TenpayUtil.getTimestamp();
            var resSign = new RequestHandler();
            resSign.setParameter("timeStamp", timeStamp);
            resSign.setParameter("nonceStr", req.getParameter("nonce_str"));
            resSign.setParameter("package", $"prepay_id={prepay_id}");
            resSign.setParameter("signType", "MD5");
            if (req.getParameter("sub_appid") != "")
                resSign.setParameter("appId", req.getParameter("sub_appid"));
            else
                resSign.setParameter("appId", req.getParameter("appid"));

            string sign = resSign.CreateMd5Sign("key", mchKey);
            return new PayDto
            {
                timeStamp = timeStamp,
                nonceStr = req.getParameter("nonce_str"),
                prepayId = prepay_id,
                paySign = sign
            };
        }

        /// <summary>
        /// 微信返回状态
        /// </summary>
        /// <param name="res"></param>
        /// <returns></returns>
        public static bool IsSuccess(ResponseHandler res)
        {
            if (res.getParameter("return_code").Equals("SUCCESS") &&
                res.getParameter("result_code").Equals("SUCCESS"))
            {
                return true;
            }
            return false;
        }

        #endregion
        /// <summary>
        /// 过滤emoji表情
        /// </summary>
        /// <param name="text"></param>
        public static string RemoveEmoji(string text)
        {
            foreach (var a in text)
            {
                byte[] bts = Encoding.UTF32.GetBytes(a.ToString());
                if (bts[0].ToString() == "253" && bts[1].ToString() == "255")
                {
                    text = text.Replace(a.ToString(), "");
                }
            }
            return text;
        }

        public static void Log(string msg)
        {
            Trace.TraceInformation(msg);
            LogHelper.WriteLog("weixin", msg);
        }
        public static void ShowErrorMsg(ResponseHandler res)
        {
            if (res.getParameter("return_code") != "SUCCESS")
                throw new Exception(res.getParameter("return_msg"));
            if (res.getParameter("result_code") != "SUCCESS")
                throw new Exception(res.getParameter("err_code_des"));
        }
    }
}
